// lcd型号JD19264C
// superzlc
// 20180414112525

#ifndef __LCD19264_H_
#define __LCD19264_H_ 1

#include <avr/io.h>
#include <util/delay.h>

//
#define LCD_LED_DDR DDRA
#define LCD_LED_PORT PORTA
#define LCD_LED_PORT_N 4

#define LCD_RST_DDR DDRA
#define LCD_RST_PORT PORTA
#define LCD_RST_PORT_N 1

#define LCD_EN_DDR DDRG
#define LCD_EN_PORT PORTG
#define LCD_EN_PORT_N 1

#define LCD_RW_DDR DDRG
#define LCD_RW_PORT PORTG
#define LCD_RW_PORT_N 0

#define LCD_RS_DDR DDRD
#define LCD_RS_PORT PORTD
#define LCD_RS_PORT_N 7

#define LCD_CSA_DDR DDRD
#define LCD_CSA_PORT PORTD
#define LCD_CSA_PORT_N 5

#define LCD_CSB_DDR DDRD
#define LCD_CSB_PORT PORTD
#define LCD_CSB_PORT_N 6

#define LCD_DATA_DDR DDRC
#define LCD_DATA_PORT PORTC
#define LCD_DATA_PIN PINC

//
#define LCD_LED_1 LCD_LED_PORT |= _BV(LCD_LED_PORT_N)
#define LCD_LED_0 LCD_LED_PORT &= ~_BV(LCD_LED_PORT_N)

#define LCD_RST_1 LCD_RST_PORT |= _BV(LCD_RST_PORT_N)
#define LCD_RST_0 LCD_RST_PORT &= ~_BV(LCD_RST_PORT_N)

#define LCD_EN_1 LCD_EN_PORT |= _BV(LCD_EN_PORT_N)
#define LCD_EN_0 LCD_EN_PORT &= ~_BV(LCD_EN_PORT_N)

#define LCD_RW_1 LCD_RW_PORT |= _BV(LCD_RW_PORT_N)
#define LCD_RW_0 LCD_RW_PORT &= ~_BV(LCD_RW_PORT_N)

#define LCD_RS_1 LCD_RS_PORT |= _BV(LCD_RS_PORT_N)
#define LCD_RS_0 LCD_RS_PORT &= ~_BV(LCD_RS_PORT_N)

#define LCD_CSA_1 LCD_CSA_PORT |= _BV(LCD_CSA_PORT_N)
#define LCD_CSA_0 LCD_CSA_PORT &= ~_BV(LCD_CSA_PORT_N)

#define LCD_CSB_1 LCD_CSB_PORT |= _BV(LCD_CSB_PORT_N)
#define LCD_CSB_0 LCD_CSB_PORT &= ~_BV(LCD_CSB_PORT_N)

#define LCD_DATA LCD_DATA_PORT
#define LCD_DATA_R LCD_DATA_PIN
//
void lcd_port_set(void)
{
	LCD_DATA_DDR |= 0xFF;
	LCD_LED_DDR |= _BV(LCD_LED_PORT_N);
	LCD_RST_DDR |= _BV(LCD_RST_PORT_N);
	LCD_EN_DDR |= _BV(LCD_EN_PORT_N);
	LCD_RW_DDR |= _BV(LCD_RW_PORT_N);
	LCD_RS_DDR |= _BV(LCD_RS_PORT_N);
	LCD_CSA_DDR |= _BV(LCD_CSA_PORT_N);
	LCD_CSB_DDR |= _BV(LCD_CSB_PORT_N);
}

void lcd_cs(uint8_t c) {
	if (c == 1) {
		LCD_CSA_0;
		LCD_CSB_0;
	} else if (c == 2) {
		LCD_CSA_1;
		LCD_CSB_0;
	} else {
		LCD_CSA_0;
		LCD_CSB_1;
	}
}

void lcd_check_busy(void)
{
	LCD_DATA_DDR = 0x00;
	LCD_RS_0;
	LCD_RW_1;
	LCD_EN_1;
	asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
	while(LCD_DATA_R & 0x10000000);
	LCD_EN_0;
	LCD_DATA_DDR = 0xFF;
}
void lcd_write_cmd(uint8_t cmd)
{
	lcd_check_busy();
	LCD_RS_0;
	LCD_RW_0;
	LCD_DATA = cmd;
	LCD_EN_1;
	asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
	LCD_EN_0;
}
void lcd_write_data(uint8_t dat)
{
	lcd_check_busy();
	LCD_RS_1;
	LCD_RW_0;
	LCD_DATA = dat;
	LCD_EN_1;
	asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
	LCD_EN_0;
}
uint8_t lcd_read_data(void)
{
	uint8_t ret;
	lcd_check_busy();
	LCD_DATA_DDR = 0x00;
	LCD_RS_1;
	LCD_RW_1;
	LCD_EN_1;
	asm("nop");asm("nop");asm("nop");asm("nop"); //_delay_us(1);
	ret = LCD_DATA_R;
	LCD_EN_0;
	LCD_DATA_DDR = 0xFF;
	return ret;
}
void lcd_set_x(uint8_t x)
{
	lcd_write_cmd(0b10111000 | (x & 0b00000111));
}
void lcd_set_y(uint8_t y)
{
	lcd_write_cmd(0b01000000 | (y & 0b00111111));
}
void lcd_set_z(uint8_t z)
{
	lcd_write_cmd(0b11000000 | (z & 0b00111111));
}
void lcd_show_switch_on_cs(uint8_t cs, uint8_t onoff) {
	lcd_cs(cs);
	if (onoff)
		lcd_write_cmd(0b00111111);
	else
		lcd_write_cmd(0b00111110);
}
void lcd_show_switch(uint8_t onoff) {
	if (onoff)
		lcd_write_cmd(0b00111111);
	else
		lcd_write_cmd(0b00111110);
}
void lcd_init(void)
{
	lcd_port_set();

	LCD_LED_0; // 8550驱动需要低电平

	LCD_RST_0;
	_delay_us(20);
	LCD_RST_1;

	lcd_cs(1);
	lcd_show_switch(1);
	lcd_set_z(0);
	lcd_cs(2);
	lcd_show_switch(1);
	lcd_set_z(0);
	lcd_cs(3);
	lcd_show_switch(1);
	lcd_set_z(0);

}
void lcd_fill(uint8_t cs, uint8_t c)
{
	lcd_cs(cs);
	uint8_t y, x;

	for (x = 0; x < 8; x++)
	{
		lcd_set_x(x);
		lcd_set_y(0);
		for (y = 0; y < 64; y++)
		{
			lcd_write_data(c);
		}
	}
}

void lcd_clear(uint8_t cs)
{
	lcd_fill(cs, 0x00);
}

// --------------------
void lcd_show_uint8_at(uint8_t x, uint8_t y, uint8_t data)
{
	lcd_cs(y / 64 + 1);
	lcd_set_x(x);
	lcd_set_y(y % 64);
	lcd_write_data(data);
}
void lcd_show_uint8_on_cs(uint8_t cs, uint8_t x, uint8_t y, uint8_t data)
{
	lcd_cs(cs);
	lcd_set_x(x);
	lcd_set_y(y);
	lcd_write_data(data);
}

void lcd_show_uint16_on_cs(uint8_t cs, uint8_t x, uint8_t y, uint16_t data)
{
	lcd_cs(cs);
	lcd_set_x(x);
	lcd_set_y(y);
	lcd_write_data((data >> 8) & 0xff);
	lcd_write_data((data) & 0xff);
}

void lcd_show_uint32_on_cs(uint8_t cs, uint8_t x, uint8_t y, uint32_t data)
{
	lcd_cs(cs);
	lcd_set_x(x);
	lcd_set_y(y);
	lcd_write_data((data >> 24) & 0xff);
	lcd_write_data((data >> 16) & 0xff);
	lcd_write_data((data >> 8) & 0xff);
	lcd_write_data((data) & 0xff);
}


#endif // __LCD19264_H_


